// pages/cate/cate.js
const app = getApp()
const {
  saveUserInfo
} = require('../../api/user')
const {
  updateCategory
} = require('../../api/bill')
const {
  arraySwap
} = require('../../lib/util')

Page({
  data: {
    category: false,
    currentIndex: 0,
    switches: [{
        name: '花 费'
      },
      {
        name: '收 入'
      }
    ],
    canSort: false,
    editIndex: -1,
    modalTitle: '编辑类别',
    inputValue: '',
    //#region 纯数据字段
    /** 屏幕高度，单位px */
    _windowHeight: null,
    /** 开始触摸时的单一项左上角y坐标 */
    _startOffsetY: null,
    /** 开始触摸位置y坐标 */
    _startPageY: null,
    /** 开始触摸项索引 */
    _startDragElementIndex: null,
    /** 滑动偏移 */
    _scrollThreshold: 0.5,
    /** 距顶部/左边多远时，触发 _scrollToUpper 事件，单位px，即上滑至屏幕顶部 */
    _upperThreshold: 100,
    /** 距底部/右边多远时，触发 _scrollToLower 事件，单位px，即下滑至屏幕底部 */
    _lowerThreshold: 100,
    /** 上滑和下滑时间，单位毫秒 */
    _scrollDuration: 1000,
    //#endregion
    /** 单一项高度 */
    elementHeight: 40,
    /** 滑动项 */
    dragElement: null,
    /** movable-view组件y轴坐标，滑动时滑动项左上角距离文档顶部纵坐标，单位px */
    movableViewY: null,
    /** 滑动过程中经过的项 */
    lastTarget: null,
  },
  onLoad: function (options) {
    this._getCategory()
    this.modal = this.selectComponent("#modal")
  },
  onShow() {
    this._getWindowHeight();
  },
  /** 提交 */
  onSure() {
    var category = this.data.category,
      currentIndex = this.data.currentIndex,
      editIndex = this.data.editIndex
    var value = this.data.inputValue
    if (value.length === 0) {
      wx.showToast({
        icon: 'none',
        title: '请填写类别名'
      })
      return
    }
    var exist = category[currentIndex].findIndex(item => {
      return item === value
    })
    if (exist >= 0) {
      wx.showToast({
        icon: 'none',
        title: '类别已存在'
      })
      return
    }
    console.log(editIndex)
    if (editIndex >= 0) {
      // 修改已有账单类别名称
      updateCategory({
        oldCate: category[currentIndex][editIndex],
        newCate: value
      }).then(res => {
        category[currentIndex][editIndex] = value
        saveUserInfo({ category }).then(res => {
          this._updateCategory(res, userInfo => {
            this.setData({
              category: category,
              editIndex: -1,
              inputValue: '',
              modalTitle: '编辑类别'
            })
            this.editIndex = -1
            this.modal.closeModal()
          })
        })
      })
    } else {
      category[currentIndex].push(value)
      saveUserInfo({ category }).then(res => {
        this._updateCategory(res, userInfo => {
          this.setData({
            category: category,
            editIndex: -1,
            inputValue: '',
            modalTitle: '编辑类别'
          })
          this.editIndex = -1
          this.modal.closeModal()
        })
      })
    }
  },
  /** 编辑 */
  onEdit(e) {
    var category = this.data.category,
      currentIndex = this.data.currentIndex
    var index = e.target.dataset.index
    this.setData({
      inputValue: category[currentIndex][index],
      modalTitle: '编辑类别'
    })
    this.modal.showModal()
  },
  /** 删除 */
  onDelete(e) {
    var category = this.data.category,
      currentIndex = this.data.currentIndex
    var index = e.target.dataset.index
    wx.showModal({
      title: '提示',
      content: `要删除类别“${category[currentIndex][index]}”嘛？`,
      success: res => {
        if (res.confirm) {
          category[currentIndex].splice(index, 1)
          saveUserInfo({ category }).then(res => {
            this._updateCategory(res, userInfo => {
              this.setData({
                category: category,
                editIndex: -1
              })
              this.editIndex = -1
            })
          })
        }
      }
    })
  },
  /** 取消编辑 */
  onCancel() {
    this.modal.closeModal()
    this.setData({
      inputValue: '',
      editIndex: -1,
      modalTitle: '编辑类别'
    })
    this.editIndex = -1
  },
  /** 数据双向绑定 */
  onInput(e) {
    this.setData({
      inputValue: e.detail.value
    })
  },
  /** 显示添加弹出框 */
  onTapAdd() {
    this.setData({
      editIndex: -1,
      modalTitle: '添加类别'
    })
    this.editIndex = -1
    this.modal.showModal()
  },
  /** 点击某一项 */
  onTapItem(e) {
    if (this.data.canSort) {
      return
    }
    var index = e.target.dataset.index
    if (this.data.editIndex === index) {
      this.setData({
        editIndex: -1
      })
    } else {
      this.setData({
        editIndex: index
      })
    }
  },
  /** 上移 */
  onUp(e) {
    var category = this.data.category.slice(),
      currentIndex = this.data.currentIndex,
      index = e.target.dataset.index
    category[currentIndex] = arraySwap(category[currentIndex], index, index - 1)
    if (this.editIndex === index) {
      this.editIndex--
    } else if (this.editIndex === index - 1) {
      this.editIndex++
    }
    this.setData({
      category: category
    })
    this.edited = true
  },
  /** 下移 */
  onDown(e) {
    var category = this.data.category.slice(),
      currentIndex = this.data.currentIndex,
      index = e.target.dataset.index
    category[currentIndex] = arraySwap(category[currentIndex], index, index + 1)
    if (this.editIndex === index) {
      this.editIndex++
    } else if (this.editIndex === index + 1) {
      this.editIndex--
    }
    this.setData({
      category: category
    })
    this.edited = true
  },
  /** 排序 */
  onTapShowSort() {
    var canSort = !this.data.canSort
    if (canSort) {
      // 开始排序
      this.editIndex = this.data.editIndex
      this.setData({
        canSort: canSort,
        editIndex: -1
      })
      this.edited = false
    } else {
      // 结束排序
      if (this.edited) {
        // 若修改过
        saveUserInfo({ category: this.data.category }).then(res => {
          this._updateCategory(res, userInfo => {
            this.setData({
              canSort: canSort,
              editIndex: -1 //this.editIndex
            })
          })
        })
      } else {
        // 若未修改
        this.setData({
          canSort: canSort,
          editIndex: -1 //this.editIndex
        })
      }
    }
  },
  /** switch切换 */
  onSwitch(e) {
    this.setData({
      currentIndex: e.detail.index,
      editIndex: -1
    })
    this.editIndex = -1;
  },


  /** 长按触发事件 */
  onLongPress(event) {
    if (!this.data.canSort) return
    console.log('[onLongPress]', event);
    // this.editIndex = this.data.editIndex;

    let dragElementIndex = event.currentTarget.dataset.index;
    let dragElement = this.data.category[this.data.currentIndex][dragElementIndex];
    this.setData({
      /** 点击项左上角y坐标 */
      _startOffsetY: event.target.offsetTop,
      /** 点击位置y坐标 */
      _startPageY: event.touches[0].pageY,
      /** 点击项索引 */
      _startDragElementIndex: dragElementIndex,
      /** 点击项 */
      dragElement,
      /** movable-view组件左上角y坐标 */
      movableViewY: event.target.offsetTop,
      editIndex: -1
    });
  },
  /**
   * 手指触摸后移动
   * - 触底或触顶时下滑或者上滑
   * - 移动movable-view
   */
  onTouchMove(event) {
    if (!this.data.canSort) return
    console.log('[onTouchMove]', event);

    // 长按事件
    if (this.data.dragElement) {
      /** 触摸点位置在显示屏幕区域左上角Y坐标 */
      let clientY = event.touches[0].clientY;
      /** 触摸点位置距离文档左上角Y坐标 */
      let pageY = event.touches[0].pageY;
      /** 和最初点击位置比较移动距离 */
      let targetMoveDistance = pageY - this.data._startPageY;
      /** 移动后的movable-view组件位置 */
      let movableViewY = this.data._startOffsetY + targetMoveDistance;
      /** 经过项索引 */
      let targetIndex = this._computeFutureIndex(targetMoveDistance, this.data._startDragElementIndex);

      this._pageScroll(clientY, pageY);

      this.setData({
        movableViewY,
        lastTarget: targetIndex
      });
    }
  },
  /** 滑动结束 */
  onTouchEnd(event) {
    if (!this.data.canSort) return
    console.log('[onTouchEnd]', event);
    if (this.data.dragElement) {
      let list = this._deepCopy(this.data.category[this.data.currentIndex]);
      /** 结束点位置y坐标 */
      let pageY = event.changedTouches[0].pageY;
      /** 和初始点击位置比较移动距离 */
      let targetMoveDistance = pageY - this.data._startPageY;
      /** 初始点击项索引 */
      let dragElementIndex = this.data._startDragElementIndex;

      /** 目标项索引 */
      const futureIndex = this._computeFutureIndex(targetMoveDistance, dragElementIndex);
      if (futureIndex !== false) {
        list.splice(futureIndex, 0, list.splice(dragElementIndex, 1)[0]); // 移动位置
      }

      this.edited = true
      let category = this.data.category;
      category[this.data.currentIndex] = list;
      this.setData({
        category: category,
        dragElement: null,
        lastTarget: null,
        editIndex: -1
      })
    }
  },
  /** 阻止滑动 */
  onHackTouchMove() {},


  _updateCategory(res, cb) {
    if (res._id && res._id.length > 0) {
      // 更新时返回 _id=""
      app.global.user._id = res._id
    } else if (!res.stats) {
      return wx.showToast({
        icon: 'none',
        title: '更新失败,请稍后重试'
      });
    }
    app.global.user.category = this.data.category
    wx.setStorageSync('userInfo', app.global.user)
    // 更新上一页数据
    app.updatePrevPage({
      category: this.data.category
    })
    typeof cb === 'function' && cb(app.global.user)
  },
  _getCategory() {
    app.getUserInfo().then(data => {
      this.setData({
        category: data.category
      })
    })
  },
  /** 获取可使用窗口高度，单位px */
  _getWindowHeight() {
    try {
      const {
        windowHeight
      } = wx.getSystemInfoSync();
      this.setData({
        _windowHeight: windowHeight
      });
    } catch (err) {
      console.error('[_getWindowHeight]', err);
    }
  },
  /** 页面滑动 */
  _pageScroll(clientY, pageY) {
    if (clientY + this.data._upperThreshold >= this.data._windowHeight) {
      // 下滑接近屏幕底部
      wx.pageScrollTo({
        scrollTop: pageY + this.data.elementHeight,
        duration: this.data._scrollDuration
      });
    } else if (clientY - this.data._lowerThreshold <= 0) {
      // 上滑接近屏幕顶部
      wx.pageScrollTo({
        scrollTop: pageY - this.data.elementHeight,
        duration: this.data._scrollDuration
      })
    }
  },
  /**
   * 计算目标索引
   * @param {number} targetMoveDistance 移动距离
   * @param {number} dtagElementIndex 初始移动项索引
   * 若轻轻拂动则返回false
   */
  _computeFutureIndex(targetMoveDistance, dragElementIndex) {
    let willInsertAfter = this._getSwapDirection(targetMoveDistance);
    if (willInsertAfter !== false) {
      /** 偏移索引 */
      let offsetElementIndex = dragElementIndex + willInsertAfter;
      /** 移动步数 */
      let step = targetMoveDistance / this.data.elementHeight;
      /** 步数补偿，当只有移动距离超过单项 _scrollThreshold 时才算有效 */
      if (step <= -1) {
        step += this.data._scrollThreshold;
      } else if (step >= 1) {
        step -= this.data._scrollThreshold;
      }
      /** 目标索引 */
      let futureIndex = parseInt(step) + offsetElementIndex;

      // 避免越界
      if (futureIndex < 0) {
        futureIndex = 0;
      } else if (futureIndex > this.data.category[this.data.currentIndex].length - 1) {
        futureIndex = this.data.category[this.data.currentIndex].length - 1;
      }

      return futureIndex;
    } else {
      return willInsertAfter;
    }
  },
  /**
   * 获取滑动方向
   * @param {number} targetMoveDistance 移动距离
   * @returns {number/boolean}
   *  - 1 下滑
   *  - -1 上滑
   *  - false 拂动，滑动距离小于一半单项高度
   */
  _getSwapDirection(targetMoveDistance) {
    if (Math.abs(targetMoveDistance) < this.data.elementHeight / 2) {
      // 轻轻拂动，滑动距离小于1/2单项高度
      return false;
    } else if (targetMoveDistance >= this.data.elementHeight / 2) {
      console.log('[_getSwapDirection] 👇👇👇');
      return 1; // 下滑
    } else if (targetMoveDistance <= this.data.elementHeight / -2) {
      console.log('[_getSwapDirection] 👆👆👆');
      return -1; // 上滑
    }
  },
  /** 深拷贝 */
  _deepCopy(obj) {
    // 只拷贝对象
    if (typeof obj !== 'object') return;
    // 根据obj的类型判断是新建一个数组还是一个对象
    var newObj = obj instanceof Array ? [] : {};
    for (var key in obj) {
      // 遍历obj,并且判断是obj的属性才拷贝
      if (obj.hasOwnProperty(key)) {
        // 判断属性值的类型，如果是对象递归调用深拷贝
        newObj[key] = typeof obj[key] === 'object' ? this._deepCopy(obj[key]) : obj[key];
      }
    }
    return newObj;
  }
})